/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mygameframework.scenes;

import com.mygameframework.sprite.Sprite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList;

/**
 *
 * @author bill
 */
public class QuadNode{
    protected static int UNIQUE_ID=0;//this is a counter var
    protected int id;
    protected QuadNode parent;
    protected QuadNode[] nodes;//son nodes
    protected boolean leaf;
    protected LinkedList containedObjects; //this list contained sprites that were involved in current node
    protected Rectangle2D bound; //the bound of current node 
    private QuadNode(){
        id=-1;
        parent=null;
        nodes=null;
        leaf=true;
        containedObjects=null;
        bound=null;
    }
    public QuadNode(QuadNode parent,int depth,Rectangle2D nodeBound){
        this.parent=parent; this.bound=nodeBound;id=UNIQUE_ID++;
        if(depth==0){//if this's a leaf node
            leaf=true;
            containedObjects=new LinkedList();
            nodes=null;
        }else{//non leaf node,then it would involve 4 nodes
            leaf=false;
            containedObjects=null;
            nodes=new QuadNode[4];
            double x=bound.getX();
            double y=bound.getY();
            double w=bound.getWidth();
            double h=bound.getHeight();
            // 3 | 2
            // ------ 4方格
            // 0 | 1
            nodes[0]=new QuadNode(this, depth-1, 
                    new Rectangle2D.Double(x, y+h/2, w/2, h/2));
            nodes[1]=new QuadNode(this, depth-1, 
                    new Rectangle2D.Double(x+w/2, y+h/2, w/2, h/2));
            nodes[2]=new QuadNode(this, depth-1, 
                    new Rectangle2D.Double(x+w/2, y, w/2, h/2));
            nodes[3]=new QuadNode(this, depth-1, 
                    new Rectangle2D.Double(x,y, w/2, h/2));
            
        }//if end
    }//construts end
    public final boolean isLeaf(){
        return leaf;  
    }
    //propagate 若为真且sprite在当前node之外,则向上层的Node调用insert
    public void insert(Sprite s,boolean propagate){
        if(bound.contains(s.getBound()) || bound.intersects(s.getBound())){
            if(isLeaf()){
                if(containedObjects==null)
                    containedObjects=new LinkedList();
                if(!containedObjects.contains(s))
                    containedObjects.add(s);
            }else{ //非leaf
                for(int i=0;i<4;i++){
                    if(nodes[i]!=null)
                        nodes[i].insert(s, false);
                }//for end
            }//if leaf else end
        }else{//不在当前节点内
            if(propagate){
                if(parent!=null)
                    parent.insert(s, true);
            }
        }
    }//insert end
    public void moveAll(double x,double y){
        if(containedObjects==null || containedObjects.isEmpty()) return;
        //TODO 未完成
    }
    public void update(long timepassed){
        if(containedObjects==null || containedObjects.isEmpty()) return;
        Sprite s;
        for(int i=0;i<containedObjects.size();i++){
            s=(Sprite)containedObjects.get(i);
            s.update(timepassed);
            if(!bound.contains(s.getBound())&& !bound.intersects(s.getBound())){
                insert((Sprite)containedObjects.remove(i), true);
                i--;
            }
        }//end for
        for(int i=0;i<containedObjects.size()-1;i++){
            Sprite s1=(Sprite) containedObjects.get(i);
            for(int j=i+1;j<containedObjects.size();j++){
                Sprite s2=(Sprite) containedObjects.get(j);
                if(s1.collidesWith(s2)){
//                    s1.addCollision(s2);
//                    s2.addCollision(s1);
                }
            }//end for
        }//end for
    }
    public void paintBounds(Graphics2D g2,Color c){
        if(c==null) c=Color.RED;
        Paint old=g2.getPaint();
        g2.setPaint(c);
        g2.draw(bound);
    }
}
